#include "TcpConnection.hpp"
#include <sstream>


namespace wd
{

//这个类是干什么的？
//TcpConnection类是对Socket的封装，提供了TCP连接的相关操作
//它包含了Socket、SocketIO、InetAddress等成员，提供了发送和接收数据的功能
//它还可以获取本地和对端的地址信息，并提供了连接状态的判断和关闭连接的功能
//TcpConnection类的构造函数接受一个文件描述符fd，初始化Socket和SocketIO对象
TcpConnection::TcpConnection(int fd)
: _sock(fd)
, _sockIO(fd)
, _localAddr(getLocalAddress())
, _peerAddr(getPeerAddress())
{}

string TcpConnection::receive()
{
    char buff[65536] = {0};//在栈上设置的64KB空间
    int ret = _sockIO.readline(buff, sizeof(buff));
    //设置第二个参数ret,是为了防止字符串内容中间有'\0'
    return string(buff, ret);
}

void TcpConnection::send(const string & msg)
{
    if(msg.size() > 0)
        _sockIO.sendn(msg.c_str(), msg.size());
}

//判断一个连接是否断开了
bool TcpConnection::isClosed() const
{
    char buff[20] ={0};
    return _sockIO.recvPeek(buff, sizeof(buff)) == 0;
}

void TcpConnection::shutdown()
{
    _sock.shutdownWrite();
}
    
string TcpConnection::toString() const
{
    std::ostringstream oss;
    oss << "tcp " << _localAddr.ip() << ":" << _localAddr.port()
        << " -> " << _peerAddr.ip() << ":" << _peerAddr.port(); 
    return oss.str();
}
    
InetAddress TcpConnection::getLocalAddress()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getsockname(_sock.fd(), (struct sockaddr*)&addr, &len);
    if(ret < 0) {
        perror("getsockname");
    }
    return InetAddress(addr);
}
    
InetAddress TcpConnection::getPeerAddress()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getpeername(_sock.fd(), (struct sockaddr*)&addr, &len);
    if(ret < 0) {
        perror("getpeername");
    }
    return InetAddress(addr);
}
}//end of namespace wd
